﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Data.SqlClient;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using CompactFormatter;

namespace RMSSever
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        static int listenport = 4567;     //侦听端口号
        Socket clientSocket;
        ArrayList Clients = new ArrayList();
        Thread clientservice;    //定义线程
        Thread threadListen;
        NetworkStream ns;
        IPEndPoint iep;

        private void Form1_Load(object sender, EventArgs e)
        {
            ListView.CheckForIllegalCrossThreadCalls = false;
            initListView();

            threadListen = new Thread(new ThreadStart(StartListening));
            threadListen.Start();
           
            //IFormatter formatter2 = new BinaryFormatter();
            //MemoryStream fromStream = new MemoryStream(byteArray);   //theBytes是序列化后的结果   
            //OrderItem[] orderBack = (OrderItem[])formatter2.Deserialize(fromStream);
            //stream.Close();

            //listBox1.Items.Add(System.Text.Encoding.Default.GetString(theBytes));
        }


        private void Test()
        {
            try
            {
                RMSClass.OrderItem[] order = getOrder("001");

                for (int i = 0; i < order.Length; i++)
                {
                    MessageBox.Show("itemID: " + order[i].itemID + "\r\norderID: " + order[i].orderID + "\r\nfoodID: " + order[i].foodID + "\r\ncookID: " + order[i].cookID + "\r\nitemState: " + order[i].itemState + "\r\nfoodName: " + order[i].foodName);
                }

                //----序列化过程----
                MemoryStream stream = new MemoryStream();
                CompactFormatter.CompactFormatter ser = new CompactFormatter.CompactFormatter();
                ser.Serialize(stream, order);
                stream.Flush();
                Byte[] theBytes = stream.ToArray();
                stream.Close();
                //------------------

                string command = "CheckOrderBack|";
                Byte[] commandbytes = System.Text.Encoding.Unicode.GetBytes(command.ToCharArray());

                Byte[] outbytes = new Byte[theBytes.Length + commandbytes.Length];

                //theBytes + commandbytes = outbytes
                Array.Copy(commandbytes, outbytes, commandbytes.Length);
                Array.Copy(theBytes, 0, outbytes, commandbytes.Length, theBytes.Length);

                string serverresponse = System.Text.Encoding.Unicode.GetString(outbytes);//转换为字符串（截取有用字符部分）
                string[] s = serverresponse.Split(new Char[] { '|' });
                string type = s[0];
                MessageBox.Show(System.Text.Encoding.Default.GetString(outbytes));
                MessageBox.Show(type);


                //将s[1]转为byte[]
                byte[] byteArray = System.Text.Encoding.Unicode.GetBytes(s[1]);

                // 反序列化
                CompactFormatter.CompactFormatter ser2 = new CompactFormatter.CompactFormatter();
                MemoryStream fromStream = new MemoryStream(byteArray);   //theBytes是序列化后的结果
                RMSClass.OrderItem[] orderBack = (RMSClass.OrderItem[])ser2.Deserialize(fromStream);

                for (int i = 0; i < orderBack.Length; i++)
                {
                    MessageBox.Show("itemID: " + orderBack[i].itemID + "\r\norderID: " + orderBack[i].orderID + "\r\nfoodID: " + orderBack[i].foodID + "\r\ncookID: " + orderBack[i].cookID + "\r\nitemState: " + orderBack[i].itemState + "\r\nfoodName: " + orderBack[i].foodName);
                }
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.ToString());
            }
        }



        private void initListView()
        {
            listView1.Groups.Clear();
            listView1.LargeImageList = imageList1;
            listView1.SmallImageList = imageList1;
            listView1.View = View.LargeIcon;
            
            //ListViewGroup group1 = new ListViewGroup("服务员");

            listView1.Groups.Add(new ListViewGroup("服务员：", HorizontalAlignment.Left));
            listView1.Groups.Add(new ListViewGroup("厨师：", HorizontalAlignment.Left));
        }

        /// <summary>
        /// 监听线程函数
        /// </summary>
        private void StartListening()
        {
            iep = new IPEndPoint(IPAddress.Any, listenport);
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            s.Bind(iep);
            s.Listen(30);

            while (true)
            {
                clientSocket = s.Accept();
                if (clientSocket != null)
                {
                    ArrayList log = new ArrayList();
                    clientservice = new Thread(new ThreadStart(ServiceClient));
                    clientservice.Start();  //启动线程进行后台运行
                    
                    log.Add("收到终端连接请求，来自：" + clientSocket.LocalEndPoint.ToString());
                    log.Add("\r\n └─ 已启动新线程进行对话处理");
                    for (int i = 0; i < log.Count; i++)
                    {
                        listBox1.Items.Add((string)log[i]);
                    }
                    listBox1.Items.Add("");
                }
            }
        }

        private void ServiceClient()
        {
            int bufLen = 0;

            while (clientSocket.Connected == true)
            {
                try
                {
                    Byte[] buffer = new Byte[1024]; //定义字节buffer变量
                    //由客户端接收数据
                    bufLen = clientSocket.Available;  //接收数据量
                    clientSocket.Receive(buffer, 0, bufLen, SocketFlags.None);  //数据存入buffer中

                    if (bufLen != 0)
                    {
                        ArrayList log = new ArrayList();    //用于保存日志，于每次收到消息时创建

                        lock (this)
                        {
                            //拆分客户端数据
                            string clientcommand = System.Text.Encoding.Unicode.GetString(buffer).Substring(0, bufLen);//转换为字符串
                            //string clientcommand = System.Text.Encoding.Unicode.GetString(buffer).Substring(0, bufLen);//转换为字符串
                            log.Add("收到消息：" + clientcommand.TrimEnd('\0'));
                            string[] info = clientcommand.TrimEnd('\0').Split(new Char[] { '|' });
                            string type = info[0];

                            if (type == "WaiterLogin")
                            {
                                string userName = info[1];
                                string userPassword = info[2];
                                
                                log.Add(" └─ 信息解析：服务员 " + userName + " 请求登录");

                                string sql = "SELECT * FROM Waiter WHERE 用户名 = '" + userName + "' AND 密码 = '" + userPassword + "'";
                                if (SQL.ReturnRows(sql) == 1)
                                {
                                    log.Add("        ├─ 登陆成功！");
                                    log.Add("        └─ 向手机端发送消息：Login Successful|");

                                    //发送登录成功的提示
                                    string command = "Login Successful|";
                                    Byte[] outbytes = System.Text.Encoding.Unicode.GetBytes(command.ToCharArray());
                                    clientSocket.Send(outbytes, outbytes.Length, 0);

                                    //此服务员还没有登录
                                    if (FindInArrayList(userName) == false)
                                    {
                                        //向ListView中添加此服务员
                                        ListViewItem lvi = new ListViewItem();
                                        lvi.Name = userName;
                                        lvi.Text = userName;
                                        lvi.ToolTipText = "已登录服务员： " + userName;
                                        lvi.Tag = info;
                                        lvi.Group = listView1.Groups[0];
                                        lvi.ImageIndex = 0;
                                        listView1.Items.Add(lvi);
                                        
                                        //为此服务员创建一个Client对象，并添加到Clients数组中
                                        EndPoint ep = clientSocket.RemoteEndPoint;
                                        Client c = new Client(userName, ep, clientservice, clientSocket);
                                        Clients.Add(c);
                                    }
                                    else
                                    {
                                        //此服务员已经登录过了
                                        log.Add("    └─ 此服务员已经登录过了！");
                                    }
                                }
                                else
                                {
                                    log.Add("        ├─ 登陆失败！");
                                    log.Add("        └─ 向手机端发送消息：Login Failed|");

                                    //发送登录失败的提示
                                    string command = "Login Failed|";
                                    Byte[] outbytes = System.Text.Encoding.Unicode.GetBytes(command.ToCharArray());
                                    clientSocket.Send(outbytes, outbytes.Length, 0);
                                }
                            }
                            if (type == "CheckFood")    //  处理服务员端发送来的CheckFood请求
                            { 
                                string tableID = info[1];
                                string foodID = info[2];
                                string cookID = info[3];
                                string custNotes = info[4];

                                log.Add(" └─ 信息解析：第 " + tableID + " 桌请求查询第 " + foodID + " 号菜的状态");
                                
                                string sql = "SELECT * FROM Menu WHERE foodID = " + foodID;
                                string command = "";

                                SqlConnection SqlConn = new SqlConnection(SQL.SqlConnString);
                                SqlConn.Open();
                                SqlCommand cmd = new SqlCommand();
                                cmd.Connection = SqlConn;
                                SqlDataReader sdr;

                                cmd.CommandText = sql;
                                cmd.CommandType = CommandType.Text;
                                sdr = cmd.ExecuteReader();
                                while (sdr.Read())
                                {
                                    //string foodID = sdr[0].ToString();    //暂时不提取foodID
                                    string foodName = sdr[1].ToString();    //提取foodName
                                    string price = sdr[2].ToString();       //提取price
                                    string intro = sdr[3].ToString();       //提取intro
                                    string foodState = sdr[4].ToString();   //提取foodState
                                    string discount = sdr[5].ToString();    //提取discount
                                    command = "CheckFoodBack|" + tableID + "|" + foodID + "|" + foodName + "|" + price + "|" + foodState + "|" + intro + "|" + discount + "|" + cookID + "|" + custNotes;
                                }
                                sdr.Close();
                                SqlConn.Close();

                                Byte[] outbytes = System.Text.Encoding.Unicode.GetBytes(command.ToCharArray());
                                clientSocket.Send(outbytes, outbytes.Length, 0);
                                //string log = "\r\n发送消息 - 目标：第" + tableID + "桌服务员手机端端发送消息：" + command;
                                log.Add("发送消息 - 目标：第 " + tableID + " 桌服务员手机端");
                                log.Add(" └─ 消息内容：" + command.TrimEnd('\0'));
                            }
                            if (type == "AddOrderItem")    //  处理服务员端发送来的AddOrder请求
                            {
                                string tableID = info[1];
                                string foodID = info[2];
                                string cookID = info[3];
                                string custNotes = info[4];

                                log.Add(" ├─ 信息解析：收到来自 第" + tableID + "桌 的菜订单");
                                log.Add(" │     ├─ 菜号：" + foodID);
                                log.Add(" │     ├─ 厨师号：" + cookID);
                                log.Add(" │     └─ 备注：" + custNotes);

                                string orderID;
                                bool check = false;

                                // 查询当前订单的桌号是否有未结账的订单
                                if (SQL.ReturnRows("SELECT * FROM OrderList WHERE tableID = '" + tableID + "' AND orderState = 0") == 1)
                                {
                                    orderID = SQL.ReturnOneData("SELECT orderID FROM OrderList WHERE tableID = '" + tableID + "' AND orderState = 0");
                                    if (orderID != "发生错误")
                                    {
                                        string sql = "INSERT INTO OrderItem(foodID,orderID,custNotes,cookID,itemState) VALUES ('" + foodID + "', '" + orderID + "', '" + custNotes + "', '" + cookID + "', 0)";
                                        check = SQL.Insert(sql);
                                    }
                                    else
                                    {
                                        MessageBox.Show("SQL.ReturnOneData发生错误！");
                                    }
                                }
                                else
                                {
                                    orderID = getOrderID();

                                    string sql = "INSERT INTO OrderItem(foodID,orderID,custNotes,cookID,itemState) VALUES ('" + foodID + "', '" + orderID + "', '" + custNotes + "', '" + cookID + "', 0)";
                                    check = SQL.Insert(sql);

                                    sql = "INSERT INTO OrderList VALUES ('" + orderID + "', '" + tableID + "',GETDATE(), 0)";
                                    check = SQL.Insert(sql);
                                }
                                
                                if (check == false)
                                {
                                    string command = "AddOrderItemFailed|" + tableID + "|" + foodID + "|" + cookID + "|" + custNotes;
                                    Byte[] outbytes = System.Text.Encoding.Unicode.GetBytes(command.ToCharArray());
                                    clientSocket.Send(outbytes, outbytes.Length, 0);
                                    log.Add(" │");
                                    log.Add(" └─ 订单处理错误！");
                                    log.Add("       └─ 向第 " + tableID + " 桌服务员端发送消息：" + command.TrimEnd('\0'));
                                }
                                else
                                {
                                    log.Add(" │");
                                    log.Add(" └─ 订单处理成功！订单号为：" + orderID);
                                }

                            }
                            if (type == "CheckOrder")
                            {
                                string tableID = info[1];

                                log.Add(" └─ 信息解析：第 " + tableID + " 桌请求查询菜单");

                                RMSClass.OrderItem[] order = getOrder(tableID);
                                //----序列化过程----
                                MemoryStream stream = new MemoryStream();
                                CompactFormatter.CompactFormatter ser = new CompactFormatter.CompactFormatter();
                                ser.Serialize(stream, order);
                                stream.Flush();
                                Byte[] theBytes = stream.ToArray();
                                stream.Close();
                                //------------------

                                string command = "CheckOrderBack|";
                                Byte[] commandbytes = System.Text.Encoding.Unicode.GetBytes(command.ToCharArray());
                               
                                Byte[] outbytes = new Byte[theBytes.Length + commandbytes.Length];

                                //theBytes + commandbytes = outbytes
                                Array.Copy(commandbytes, outbytes, commandbytes.Length);
                                Array.Copy(theBytes, 0, outbytes, commandbytes.Length, theBytes.Length);

                                clientSocket.Send(outbytes, outbytes.Length, 0);
                                log.Add("发送消息 - 目标：第 " + tableID + " 桌服务员手机端");
                                log.Add(" └─ 消息内容：（序列化内容）");
                            }
                            if (type == "DeleteOrderItem")
                            {
                                string itemID = info[1];
                                string tableID = info[2];
                                log.Add(" ├─ 信息解析：第 " + tableID + " 桌顾客要求取消ItemID为 " + itemID.TrimEnd('\0') + " 的菜");
                                bool check = SQL.Update("DELETE FROM OrderItem WHERE itemID = " + itemID);
                                if (check == true)
                                {
                                    log.Add(" └─ 取消成功");
                                }
                                else
                                {
                                    log.Add(" └─ 取消失败");
                                }
                            }

                        }
                        // 向ListBox中写入日志
                        for (int i = 0; i < log.Count; i++)
                        {
                            listBox1.Items.Add((string)log[i]);
                        }
                        listBox1.Items.Add("");
                    }
                }
                catch (Exception exp)
                {
                    MessageBox.Show("发生错误！" + exp.ToString());
                }
            }
            clientSocket.Shutdown(SocketShutdown.Both);
            clientSocket.Close();
        }


        /// <summary>
        /// 获得一个可用的OrderID
        /// </summary>
        /// <returns>OrderID值</returns>
        private string getOrderID()
        {
            //获得系统日期，格式为：2009-09-18，去除其中的“-”，结果为：20090918
            string date = System.DateTime.Now.ToShortDateString().Replace("-", "");
            
            //获得系统时间，格式为：20:23
            string time = System.DateTime.Now.ToShortTimeString();
            
            //从OrderList表中获得可用编号
            string availableID = SQL.ReturnOneData("SELECT COUNT(*)+1 FROM OrderList");
            
            string orderID = date + "-" + availableID;
            return orderID;
        }



        /// <summary>
        /// 在Clients中寻找某个用户名是否已经登录
        /// </summary>
        /// <param name="userName">待检测的用户名</param>
        /// <returns>已经登录返回true，未登录返回false</returns>
        private bool FindInArrayList(string userName)
        {
            bool r = false;

            foreach (object o in Clients)
            {
                string Name = ((Client)o).Name;
                if (Name == userName)
                {
                    r = true;
                    break;
                }
            }
            return r;
        }


        /// <summary>
        /// 通过tableID获得OrderItem[]格式的菜单
        /// </summary>
        /// <param name="tableID">桌号</param>
        /// <returns>tableID对应的当前用餐菜单</returns>
        private RMSClass.OrderItem[] getOrder(string tableID)
        {
            string orderID = SQL.ReturnOneData("SELECT orderID FROM OrderList WHERE orderState = 0 AND tableID = '" + tableID + "'");
            string orderNumberString = SQL.ReturnOneData("SELECT COUNT(*) FROM OrderItem WHERE orderID = '" + orderID + "'");
            int orderNumber = Int32.Parse(orderNumberString);

            RMSClass.OrderItem[] order = new  RMSClass.OrderItem[orderNumber];

            SqlConnection SqlConn = new SqlConnection(SQL.SqlConnString);
            SqlConn.Open();
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = SqlConn;
            SqlDataReader sdr;

            string sql = "SELECT * FROM OrderItem WHERE orderID = '" + orderID + "'";
            cmd.CommandText = sql;
            cmd.CommandType = CommandType.Text;
            sdr = cmd.ExecuteReader();

            for (int i = 0; i < orderNumber; i++)
            {
                if(sdr.Read()==true)
                {
                    string itemID = sdr[0].ToString();      //提取itemID
                    string foodID = sdr[1].ToString();      //提取foodID
                    //string orderID = sdr[2].ToString();   //暂时不用提取orderID
                    string custNotes = sdr[3].ToString();   //提取custNotes
                    string cookID = sdr[4].ToString();      //提取cookID
                    string itemState = sdr[5].ToString();   //提取itemState

                    string foodName = SQL.ReturnOneData("SELECT foodName FROM Menu WHERE foodID = '" + foodID + "'");

                    //string foodName = "我真是不明白了！这个名字比任何一个真名字都长啊！";
                    RMSClass.OrderItem item = new RMSClass.OrderItem(itemID, foodID, orderID, custNotes, cookID, itemState, foodName);
                    order[i] = item;
                } 
            }
            sdr.Close();
            SqlConn.Close();

            return order;
        }


        ////private void AddLog(string logString, Color fontColor)
        //{
        //    richTextBox1.AppendText(logString + "\r\n");
        //    int p1 = richTextBox1.Text.IndexOf(logString);
        //    int p2 = logString.Length;
        //    richTextBox1.ForeColor = Color.Chartreuse;
        //    richTextBox1.Select(p1, p2);
        //    richTextBox1.SelectionColor = fontColor;
        //    richTextBox1.Refresh();
        //}

    }
}